home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 32 / Amiga Format AFCD32 (Nov 1998, Issue 117).iso / -seriously_amiga- / programming / c / mesa-2.6 / src-glu / tess.c < prev   
C/C++ Source or Header  |  1998-08-10  |  8KB  |  334 lines

  1. /* $Id: tess.c,v 1.8 1998/02/04 00:27:58 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  2.6
  6.  * Copyright (C) 1995-1997  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * tess.c
  26.  *
  27.  * Version 1.0  27 Jun 1998
  28.  * by Jarno van der Linden
  29.  * jarno@kcbbs.gen.nz
  30.  *
  31.  * File created from tess.c ver 1.8 and glu.h ver 1.9 using GenProtos
  32.  *
  33.  */
  34.  
  35.  
  36. /*
  37.  * This file is part of the polygon tesselation code contributed by
  38.  * Bogdan Sikorski
  39.  */
  40.  
  41.  
  42. #ifdef PC_HEADER
  43. #include "all.h"
  44. #else
  45. #include <math.h>
  46. #include <stdlib.h>
  47. #include "tess.h"
  48. #endif
  49.  
  50.  
  51.  
  52. extern void tess_test_polygon(GLUtriangulatorObj *);
  53. extern void tess_find_contour_hierarchies(GLUtriangulatorObj *);
  54. extern void tess_handle_holes(GLUtriangulatorObj *);
  55. extern void tess_tesselate(GLUtriangulatorObj *);
  56. extern void tess_tesselate_with_edge_flag(GLUtriangulatorObj *);
  57. static void delete_contours(GLUtriangulatorObj *);
  58.  
  59. #ifdef __CYGWIN32__
  60. #define _CALLBACK
  61. #else
  62. #define _CALLBACK CALLBACK
  63. #endif
  64.  
  65. void init_callbacks(tess_callbacks *callbacks)
  66. {
  67.    callbacks->begin = ( void (_CALLBACK*)(GLenum) ) 0;
  68.    callbacks->edgeFlag = ( void (_CALLBACK*)(GLboolean) ) 0;
  69.    callbacks->vertex = ( void (_CALLBACK*)(void*) ) 0;
  70.    callbacks->end = ( void (_CALLBACK*)(void) ) 0;
  71.    callbacks->error = ( void (_CALLBACK*)(GLenum) ) 0;
  72. }
  73.  
  74. void tess_call_user_error(GLUtriangulatorObj *tobj,
  75.     GLenum gluerr)
  76. {
  77.     if(tobj->error==GLU_NO_ERROR)
  78.         tobj->error=gluerr;
  79.     if(tobj->callbacks.error!=NULL)
  80.         (tobj->callbacks.error)(gluerr);
  81. }
  82.  
  83. __asm __saveds GLUtriangulatorObj* APIENTRY gluNewTess( void )
  84. {
  85.    GLUtriangulatorObj *tobj;
  86.  
  87.     if((tobj=(GLUtriangulatorObj *)
  88.         malloc(sizeof(struct GLUtriangulatorObj)))==NULL)
  89.         return NULL;
  90.     tobj->contours=tobj->last_contour=NULL;
  91.     init_callbacks(&tobj->callbacks);
  92.     tobj->error=GLU_NO_ERROR;
  93.     tobj->current_polygon=NULL;
  94.     tobj->contour_cnt=0;
  95.     return tobj;
  96. }
  97.  
  98.  
  99. __asm __saveds void APIENTRY gluTessCallback( register __a0 GLUtriangulatorObj *tobj, register __d0 GLenum which,
  100.                                               register __a1 void (CALLBACK *fn)() )
  101. {
  102.     switch(which)
  103.     {
  104.         case GLU_BEGIN:
  105.             tobj->callbacks.begin = (void (_CALLBACK*)(GLenum)) fn;
  106.             break;
  107.         case GLU_EDGE_FLAG:
  108.             tobj->callbacks.edgeFlag = (void (_CALLBACK*)(GLboolean)) fn;
  109.             break;
  110.         case GLU_VERTEX:
  111.             tobj->callbacks.vertex = (void (_CALLBACK*)(void *)) fn;
  112.             break;
  113.         case GLU_END:
  114.             tobj->callbacks.end = (void (_CALLBACK*)(void)) fn;
  115.             break;
  116.         case GLU_ERROR:
  117.             tobj->callbacks.error = (void (_CALLBACK*)(GLenum)) fn;
  118.             break;
  119.         default:
  120.             tobj->error=GLU_INVALID_ENUM;
  121.             break;
  122.     }
  123. }
  124.  
  125.  
  126.  
  127. __asm __saveds void APIENTRY gluDeleteTess( register __a0 GLUtriangulatorObj *tobj )
  128. {
  129.     if(tobj->error==GLU_NO_ERROR && tobj->contour_cnt)
  130.         /* was gluEndPolygon called? */
  131.         tess_call_user_error(tobj,GLU_TESS_ERROR1);
  132.     /* delete all internal structures */
  133.     delete_contours(tobj);
  134.     free(tobj);
  135. }
  136.  
  137.  
  138. __asm __saveds void APIENTRY gluBeginPolygon( register __a0 GLUtriangulatorObj *tobj )
  139. {
  140. /*
  141.     if(tobj->error!=GLU_NO_ERROR)
  142.         return;
  143. */
  144.         tobj->error = GLU_NO_ERROR;
  145.     if(tobj->current_polygon!=NULL)
  146.     {
  147.         /* gluEndPolygon was not called */
  148.         tess_call_user_error(tobj,GLU_TESS_ERROR1);
  149.         /* delete all internal structures */
  150.         delete_contours(tobj);
  151.     }
  152.     else
  153.     {
  154.         if((tobj->current_polygon=
  155.             (tess_polygon *)malloc(sizeof(tess_polygon)))==NULL)
  156.         {
  157.             tess_call_user_error(tobj,GLU_OUT_OF_MEMORY);
  158.             return;
  159.         }
  160.         tobj->current_polygon->vertex_cnt=0;
  161.         tobj->current_polygon->vertices=
  162.             tobj->current_polygon->last_vertex=NULL;
  163.     }
  164. }
  165.  
  166.  
  167. __asm __saveds void APIENTRY gluEndPolygon( register __a0 GLUtriangulatorObj *tobj )
  168. {
  169.     /*tess_contour *contour_ptr;*/
  170.  
  171.     /* there was an error */
  172.     if(tobj->error!=GLU_NO_ERROR) goto end;
  173.  
  174.     /* check if gluBeginPolygon was called */
  175.     if(tobj->current_polygon==NULL)
  176.     {
  177.         tess_call_user_error(tobj,GLU_TESS_ERROR2);
  178.         return;
  179.     }
  180.     tess_test_polygon(tobj);
  181.     /* there was an error */
  182.     if(tobj->error!=GLU_NO_ERROR) goto end;
  183.  
  184.     /* any real contours? */
  185.     if(tobj->contour_cnt==0)
  186.     {
  187.         /* delete all internal structures */
  188.         delete_contours(tobj);
  189.         return;
  190.     }
  191.     tess_find_contour_hierarchies(tobj);
  192.     /* there was an error */
  193.     if(tobj->error!=GLU_NO_ERROR) goto end;
  194.  
  195.     tess_handle_holes(tobj);
  196.     /* there was an error */
  197.     if(tobj->error!=GLU_NO_ERROR) goto end;
  198.  
  199.     /* if no callbacks, nothing to do */
  200.     if(tobj->callbacks.begin!=NULL && tobj->callbacks.vertex!=NULL &&
  201.         tobj->callbacks.end!=NULL)
  202.     {
  203.         if(tobj->callbacks.edgeFlag==NULL)
  204.             tess_tesselate(tobj);
  205.         else
  206.             tess_tesselate_with_edge_flag(tobj);
  207.     }
  208.  
  209. end:
  210.     /* delete all internal structures */
  211.     delete_contours(tobj);
  212. }
  213.  
  214.  
  215. __asm __saveds void APIENTRY gluNextContour( register __a0 GLUtriangulatorObj *tobj, register __d0 GLenum type )
  216. {
  217.     if(tobj->error!=GLU_NO_ERROR)
  218.         return;
  219.     if(tobj->current_polygon==NULL)
  220.     {
  221.         tess_call_user_error(tobj,GLU_TESS_ERROR2);
  222.         return;
  223.     }
  224.     /* first contour? */
  225.     if(tobj->current_polygon->vertex_cnt)
  226.         tess_test_polygon(tobj);
  227. }
  228.  
  229.  
  230. __asm __saveds void APIENTRY gluTessVertex( register __a0 GLUtriangulatorObj *tobj, register __a1 GLdouble v[3], register __a2 void *data )
  231. {
  232.     tess_polygon *polygon=tobj->current_polygon;
  233.     tess_vertex *last_vertex_ptr;
  234.  
  235.     if(tobj->error!=GLU_NO_ERROR)
  236.         return;
  237.     if(polygon==NULL)
  238.     {
  239.         tess_call_user_error(tobj,GLU_TESS_ERROR2);
  240.         return;
  241.     }
  242.     last_vertex_ptr=polygon->last_vertex;
  243.     if(last_vertex_ptr==NULL)
  244.     {
  245.         if((last_vertex_ptr=(tess_vertex *)
  246.             malloc(sizeof(tess_vertex)))==NULL)
  247.         {
  248.             tess_call_user_error(tobj,GLU_OUT_OF_MEMORY);
  249.             return;
  250.         }
  251.         polygon->vertices=last_vertex_ptr;
  252.         polygon->last_vertex=last_vertex_ptr;
  253.         last_vertex_ptr->data=data;
  254.         last_vertex_ptr->location[0]=v[0];
  255.         last_vertex_ptr->location[1]=v[1];
  256.         last_vertex_ptr->location[2]=v[2];
  257.         last_vertex_ptr->next=NULL;
  258.         last_vertex_ptr->previous=NULL;
  259.         ++(polygon->vertex_cnt);
  260.     }
  261.     else
  262.     {
  263.         tess_vertex *vertex_ptr;
  264.  
  265.         /* same point twice? */
  266.         if(fabs(last_vertex_ptr->location[0]-v[0]) < EPSILON &&
  267.             fabs(last_vertex_ptr->location[1]-v[1]) < EPSILON &&
  268.             fabs(last_vertex_ptr->location[2]-v[2]) < EPSILON)
  269.         {
  270.             tess_call_user_error(tobj,GLU_TESS_ERROR6);
  271.             return;
  272.         }
  273.         if((vertex_ptr=(tess_vertex *)
  274.             malloc(sizeof(tess_vertex)))==NULL)
  275.         {
  276.             tess_call_user_error(tobj,GLU_OUT_OF_MEMORY);
  277.             return;
  278.         }
  279.         vertex_ptr->data=data;
  280.         vertex_ptr->location[0]=v[0];
  281.         vertex_ptr->location[1]=v[1];
  282.         vertex_ptr->location[2]=v[2];
  283.         vertex_ptr->next=NULL;
  284.         vertex_ptr->previous=last_vertex_ptr;
  285.         ++(polygon->vertex_cnt);
  286.         last_vertex_ptr->next=vertex_ptr;
  287.         polygon->last_vertex=vertex_ptr;
  288.     }
  289. }
  290.  
  291.  
  292. static void delete_contours(GLUtriangulatorObj *tobj)
  293. {
  294.     tess_polygon *polygon=tobj->current_polygon;
  295.     tess_contour *contour,*contour_tmp;
  296.     tess_vertex *vertex,*vertex_tmp;
  297.  
  298.     /* remove current_polygon list - if exists due to detected error */
  299.     if(polygon!=NULL)
  300.     {
  301.         if (polygon->vertices)
  302.         {
  303.             for(vertex=polygon->vertices;vertex!=polygon->last_vertex;)
  304.             {
  305.                 vertex_tmp=vertex->next;
  306.                 free(vertex);
  307.                 vertex=vertex_tmp;
  308.             }
  309.             free(vertex);
  310.         }
  311.         free(polygon);
  312.         tobj->current_polygon=NULL;
  313.     }
  314.     /* remove all contour data */
  315.     for(contour=tobj->contours;contour!=NULL;)
  316.     {
  317.         for(vertex=contour->vertices;vertex!=contour->last_vertex;)
  318.         {
  319.             vertex_tmp=vertex->next;
  320.             free(vertex);
  321.             vertex=vertex_tmp;
  322.         }
  323.         free(vertex);
  324.         contour_tmp=contour->next;
  325.         free(contour);
  326.         contour=contour_tmp;
  327.     }
  328.     tobj->contours=tobj->last_contour=NULL;
  329.     tobj->contour_cnt=0;
  330. }
  331.  
  332.  
  333.  
  334.